package com.base.data.elasticsearch.util;

import cn.hutool.core.util.ReflectUtil;
import com.base.data.elasticsearch.ElasticsearchException;
import lombok.NonNull;
import org.apache.logging.log4j.util.Strings;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.persistence.Id;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Optional;
import java.util.UUID;

public class RefectUtil {

    private static final Logger log = LoggerFactory.getLogger(RefectUtil.class);

    private static <T> Optional<Field> refectIdField(T entity) {
        Class<T> clazz = (Class<T>) entity.getClass();
        final Field[] fields = clazz.getDeclaredFields();
        Optional<Field> field = Optional.empty();
        final Optional<Field> first = Arrays.stream(fields).filter(p -> p.isAnnotationPresent(Id.class)).findFirst();
        if (first.isPresent()) {
            field = first;
        } else {
            final Optional<Field> firstId = Arrays.stream(fields).filter(p -> p.isAnnotationPresent(org.springframework.data.annotation.Id.class)).findFirst();
            if (firstId.isPresent()) {
                field = firstId;
            } else {
                final Optional<Field> idOptionalField = Arrays.stream(fields).filter(p -> "id".equalsIgnoreCase(p.getName())).findFirst();
                if (idOptionalField.isPresent()) {
                    field = idOptionalField;
                }
            }
        }
        return field;
    }

    public static <T> String refectEntityIdValue(T entity) {
        final Optional<Field> optionalField = refectIdField(entity);
        if (optionalField.isPresent()) {
            final Field field = optionalField.get();
            String entityId = refectIdValue(entity, field);
            if (Strings.isBlank(entityId)) {
                entityId = UUID.randomUUID().toString().replace("-", "");
                log.debug("no id prop,persistent id fail, genera uuid:{}",entityId);
                //id属性持久化到entity
                ReflectUtil.setFieldValue(entity, field, entityId);
            }
            return entityId;
        }
        final String entityId = UUID.randomUUID().toString().replace("-", "");
        log.debug("Entity No Id Field,genera uuid:{},entity:{}",entityId,entity);
        return entityId;
    }

    private static <T> String refectIdValue(T entity, Field field) {
        final Object fieldValue = ReflectUtil.getFieldValue(entity, field);
        if (null != fieldValue) {
            if (fieldValue instanceof String) {
                return (String) fieldValue;
            } else {
                return String.valueOf(fieldValue);
            }
        }
        return Strings.EMPTY;
    }

    public static void refectFixedScriptTypeForINLINE(@NonNull Script entity) {
        if(entity.getType() == ScriptType.INLINE) {
            String inline = "inline";
            if(!entity.getType().getParseField().getPreferredName().equalsIgnoreCase(inline)) {
                Field field = ReflectUtil.getField(Script.class, "type");
                Field parseField = ReflectUtil.getField(ScriptType.class, "parseField");
                ScriptType scriptType = ScriptType.INLINE;
                ReflectUtil.setFieldValue(scriptType, parseField, new ParseField(inline));
                ReflectUtil.setFieldValue(entity, field, scriptType);
            }
        }
    }

}
